#ifndef SOFTPLC_H
#define SOFTPLC_H
// #include "ArduinoJson.h"
// #include "msgpack.hpp"
#include "iec_types_all.h"
typedef uint8_t u8;
#define CCMRAM __attribute__((section(".ccmram")))

typedef struct
{
    void *ptr;
    __IEC_types_enum type;
} dbgvardsc_t;

extern const dbgvardsc_t dbgvardsc[];
#define __Unpack_desc_type dbgvardsc_t

#ifdef ONLINE_DEBUG
#define __Unpack_case_t(TYPENAME)                                                \
    case TYPENAME##_ENUM:                                                        \
        *flags = ((__IEC_##TYPENAME##_t *)varp)->flags;                          \
        forced_value_p = *real_value_p = &((__IEC_##TYPENAME##_t *)varp)->value; \
        break;

#define __Unpack_case_p(TYPENAME)                                 \
    case TYPENAME##_O_ENUM:                                       \
        *flags = __IEC_OUTPUT_FLAG;                               \
    case TYPENAME##_P_ENUM:                                       \
        *flags |= ((__IEC_##TYPENAME##_p *)varp)->flags;          \
        *real_value_p = ((__IEC_##TYPENAME##_p *)varp)->value;    \
        forced_value_p = &((__IEC_##TYPENAME##_p *)varp)->fvalue; \
        break;
#else
#define __Unpack_case_t(TYPENAME)                                                \
    case TYPENAME##_ENUM:                                                        \
        *flags = ((__IEC_##TYPENAME##_t *)varp)->flags;                          \
        forced_value_p = *real_value_p = &((__IEC_##TYPENAME##_t *)varp)->value; \
        break;

#define __Unpack_case_p(TYPENAME)                              \
    case TYPENAME##_O_ENUM:                                    \
        *flags = __IEC_OUTPUT_FLAG;                            \
    case TYPENAME##_P_ENUM:                                    \
        *flags |= ((__IEC_##TYPENAME##_p *)varp)->flags;       \
        *real_value_p = ((__IEC_##TYPENAME##_p *)varp)->value; \
        break;
#endif
typedef enum
{
    Broken,
    Started,
    Stopped,
    Disconnected,
    Empty
} PLC_STATUS;
#define BUFFER_FREE 0
#define BUFFER_BUSY 1


void setPLCShutdown();
void plc_run_start();
void plc_run_end();

//调试接口
extern char stxbuf[];
int regVari(const char *buf, int len);
int readVari();
// int GetVars(DynamicJsonDocument &doc, char *tx, int txlen);
int system_cmd(const u8 *rx, int rxlen, u8 *tx, int txlen);
int lastbuildPLC_md5(u8 *txbuf);

extern const char PLC_ID[];
extern const unsigned short BUILD_NUMBER;

extern unsigned long long common_ticktime__;
extern TIME __CURRENT_TIME;
extern char *buffer_cursor;
extern char debug_buffer[];
extern long buffer_state;

//PLC函数
extern "C"
{
    int __init();
    void __run();
    void runPLC();
    void __cleanup(void);
    void ResetDebugVariables(void);
    int startPLC();
    int stopPLC();
    extern int CheckRetainBuffer(void);
    extern void InitRetain(void);
    void startRetainThd();
    extern void InitiateDebugTransfer(void);
    extern void CleanupRetain(void);
    void Remind(unsigned int offset, unsigned int count, void *p);
    void Retain(unsigned int offset, unsigned int count, void *p);
    void RegisterDebugVariable(unsigned int idx, void *force);
    int RetainCmp(unsigned int offset, unsigned int count, void *p);
    void RetainBufferClose();
    int TryEnterDebugSection(void);
    long AtomicCompareExchange(long *atomicvar, long compared, long exchange);
    void LeaveDebugSection(void);
    void __init_debug(void);
    void __publish_debug(void);
    int GetDebugData(unsigned long *tick, unsigned long *size, void **buffer);
    int endDebugData();
    void suspendDebug(int disable);
    int GetPLCstatus(char *tx, int txlen);
    void resumeDebug(void);
    int LogMessage(uint8_t level, char *buf, uint32_t size);
    void PLC_GetTime(IEC_TIME *CURRENT_TIME);
    int WaitDebugData(unsigned long *tick);
    unsigned int GetRetainSize(void);
    void *UnpackVar(const __Unpack_desc_type *dsc, void **real_value_p, char *flags);
}
void setPLCShutdown();
void setReboot();
#endif
